extends TimeLord

class CharacterGeo:
	extends Object
	var width
	var height
	var total_height
	var bottom_width
	var color
	var chatbox_width = 300
	var chatbox_color = ColorN("white")

	func _init(_width=0,
			_height=0,
			_total_height=0,
			_color = ColorN("white"),
			_bottom_width=0):

		width = _width
		height = _height
		total_height = _total_height
		bottom_width = _bottom_width
		color = _color

signal dialogue_ended

const MORPH_ANITIME = 0.5
const ROLL_ANITIME = 0.5

onready var screen_w = get_viewport().size.x
onready var screen_h = get_viewport().size.y
var sin60 = sqrt(3)/2
var sin30 = 1.0/2.0

var PONY = null
var PONY_INNER = null
var PONY_MARGIN = 20
var PONY_DIAGONAL_MARGIN = PONY_MARGIN/sin30

var HUMAN = null

var CHATBOX_V_OFFSET = PONY_MARGIN*2

var current_shape = CharacterGeo.new()
var current_inner_shape = CharacterGeo.new()

var current_actor = PONY
var previous_actor = PONY

var inner_poly = Polygon2D.new()
var outer_poly = Polygon2D.new()

var current_dialogue = null
var current_dialogue_pos = 0

var chatbox = null

var blinker = Blinker.new("press ENTER to advance")

func _init():
	listening = false

func _ready():

	add_child(blinker)
	blinker.deactivate()

	for p in [outer_poly,inner_poly]:
		p.z_as_relative = true
		add_child(p)

	init_endpoints()

	clone(PONY, current_shape)
	clone(PONY_INNER, current_inner_shape)

	chatbox = ChatBox.new()
	add_child(chatbox)
	chatbox.add_message("Hello itsy bitsy gamedev guy with enormous ego and little money")

func start_dialogue(dialogue):
	current_dialogue = dialogue
	current_dialogue_pos = 0
	advance()
	roll_in()

func advance():
	var erasing = false

	if current_dialogue_pos == len(current_dialogue.lines):
		end_dialogue()
		return

	advancing_sound()
	var line = current_dialogue.lines[current_dialogue_pos]
	current_actor = PONY if line.actor == Saying.PONY else HUMAN
	if previous_actor != current_actor:
		morph_to(current_actor)
		erasing = true
	if line.clear_buffer:
		erasing = true
	if erasing:
		chatbox.clear()
		send_message_after(ChatMessage.ERASE_ANITIME+0.05, line.text)
	else:
		send_message(line.text)

	previous_actor = current_actor
	current_dialogue_pos += 1
	ignore_input_for(MORPH_ANITIME)


func send_message_after(delay,message):
	execute_after(delay,"send_message",message)

func send_message(message):
	chatbox.add_message(message)

func advancing_sound():
	var p = SDRandPitch2D.new("res://sounds/hm.ogg")
	p.volume_db = 10.0
	p.position = get_viewport().size/2
	add_child(p)
	p.play()

func roll_in():
	listening = true
	blinker.activate()
	var tw = SDTween.new()
	tw.interpolate_property(self,"position", Vector2(0,screen_h),Vector2(0,0),ROLL_ANITIME,Tween.TRANS_CUBIC,Tween.EASE_IN_OUT)
	add_child(tw)
	tw.start()
	visible = true

func roll_out():
	listening = false
	blinker.deactivate()
	var tw = SDTween.new(self,"come_invisible")
	tw.interpolate_property(self,"position", Vector2(0,0),Vector2(0,screen_h),ROLL_ANITIME,Tween.TRANS_CUBIC,Tween.EASE_IN_OUT)
	add_child(tw)
	tw.start()

func come_invisible():
	visible = false

func _process(delta):
	if visible:
		update_shape()


func clone(source, target):
	for p in source.get_property_list():
		var n = p["name"]
		target.set(n, source.get(n))

func init_endpoints():
	PONY = CharacterGeo.new(0.8 * screen_w, 0.4 * screen_h)
	PONY.total_height = PONY.width*sin60
	PONY.chatbox_width = PONY.width*0.6

	PONY_INNER = CharacterGeo.new(
						PONY.width - 2*PONY_DIAGONAL_MARGIN*sin60,
						PONY.height + PONY_MARGIN
						)
	PONY_INNER.total_height = PONY_INNER.width*sin60
	PONY_INNER.color = Color8(255,0,255,255)

	HUMAN = CharacterGeo.new(
						0.6 * screen_w,
						0.5 * screen_h
						)

	HUMAN.bottom_width = HUMAN.width
	HUMAN.total_height = HUMAN.width
	HUMAN.chatbox_width = HUMAN.width*0.8
	HUMAN.chatbox_color = ColorN("black")

func make_vertex_pool(shape):
	var poly_pool = PoolVector2Array()
	var bottom_height = shape.height + shape.total_height

	for v in [
		Vector2(screen_w/2 - shape.width/2, shape.height),
		Vector2(screen_w/2 + shape.width/2, shape.height),
		Vector2(screen_w/2 + shape.bottom_width/2, bottom_height),
		Vector2(screen_w/2 - shape.bottom_width/2, bottom_height),
		]:
			poly_pool.append(v)
	return poly_pool

func morph(object, destination):
	for p in destination.get_property_list():
#		var o = get(object)
		var n = p["name"]
		var tw = SDTween.new()
		tw.interpolate_property(object, n, object.get(n),destination.get(n),MORPH_ANITIME,Tween.TRANS_CUBIC,Tween.EASE_OUT)
		add_child(tw)
		tw.start()


func update_shape():
	outer_poly.polygon = make_vertex_pool(current_shape)
	inner_poly.polygon = make_vertex_pool(current_inner_shape)
	inner_poly.color = current_inner_shape.color
	chatbox.rect_position = Vector2(screen_w/2 - current_shape.chatbox_width/2, current_shape.height + CHATBOX_V_OFFSET)
	chatbox.rect_size = Vector2(current_shape.chatbox_width,screen_h - chatbox.rect_position.y)
	chatbox.modulate = current_shape.chatbox_color

func anti_actor(actor):
	if actor == HUMAN:
		return PONY
	return HUMAN

func morph_to(dest):
	morph(current_shape, dest)
	if dest == PONY:
		morph(current_inner_shape, PONY_INNER)
	else:
		morph(current_inner_shape, dest)
	current_actor = dest

func end_dialogue():
	emit_signal("dialogue_ended")
	roll_out()

func _input(event):
	if listening:
		if event.is_action_pressed("ui_accept"):
			advance()
#		print("morphing\n")
#		var dest = anti_actor(current_actor)
#		morph_to(dest)
